package datamining.algorithms.prefixspan;

import java.util.Collection;
import java.util.Map;

import datamining.common.Canonizable;
import datamining.common.Frequented;
import datamining.miner.chain.Extension;
import datamining.miner.chain.SearchLatticeNode;
import datamining.miner.enviroment.LocalEnvironment;
import datamining.miner.general.Embedding;
import datamining.miner.general.Fragment;
import datamining.miner.general.Frequency;
import datamining.miner.general.SequenceFragment;
import datamining.sequence.HPSequence;
import datamining.sequence.IndexedItem;
import datamining.sequence.ItemSet;
import datamining.sequence.Sequence;
import de.parsemis.algorithms.gSpan.GSpanExtension;
import de.parsemis.algorithms.gSpan.GThreadEnvironment;

/**
 * <p>
 * 创建于 2012-12-1 下午5:10:05
 * 
 * @author xujinghu (jinghuxu@nudt.edu.cn) <br>
 *         Copyright 2012 xujinghu <br>
 *         Lisence: Apache
 */
public class PrefixCode<ItemType> extends SearchLatticeNode<ItemType> implements
		Comparable<PrefixCode<ItemType>>, Canonizable, Frequented {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Sequence<ItemType> prefix;
	public IndexedItem<ItemType> firstItem = null;
	public IndexedItem<ItemType> lastItem = null;
	public Frequency frequency;
	public int threadIdx;
	private PThreadEnvironment<ItemType> tenv;
	private SequenceFragment<ItemType> fragment;

	/**
	 * @param prefix
	 *                the original sequence this PrefixSpan sequence should
	 *                represent
	 * @param idx
	 *                the index in the sequence database
	 * @param frequency
	 *                the frequency of this sequence
	 */
	public PrefixCode(SequenceFragment<ItemType> frag,
			Sequence<ItemType> prefix,
			final PThreadEnvironment<ItemType> tenv) {
		this.threadIdx = tenv.threadIdx;
		this.tenv = tenv;
		this.prefix = prefix;
		this.fragment = frag;
		this.firstItem = prefix.toHPSequence().getFirstItem();
		this.lastItem = prefix.toHPSequence().getLastItem();
	}

	@Override
	public Collection<Embedding<ItemType>> allEmbeddings() {
		return fragment.getEmbeddings();
	}

	@Override
	public int compareTo(PrefixCode<ItemType> o) {
		return this.prefix.compareTo(o.toSequence());
	}

	@Override
	public PrefixCode<ItemType> extend(Extension<ItemType> extension) {
		assert extension instanceof PrefixSpanExtension;
		return ((PrefixSpanExtension<ItemType>) extension).applyTo(this);
	}

	@Override
	public void finalizeIt() {
		// TODO Auto-generated method stub

	}

	@Override
	public Frequency frequency() {
		return toFragment().frequency();
	}

	public IndexedItem<ItemType> getFirstItem() {
		return this.firstItem;
	}

	public IndexedItem<ItemType> getLatItem() {
		return this.lastItem;
	}

	@Override
	public int getThreadNumber() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public boolean isCanonical() {
		return true;
	}

	@Override
	public void release() {
		// TODO Auto-generated method stub

	}

	@Override
	public void setThreadNumber(int threadIdx) {
		// TODO Auto-generated method stub

	}

	@Override
	public SequenceFragment<ItemType> toFragment() {
		return fragment;
	}

	public String toString() {
		return fragment.toString();
	}

	public Sequence<ItemType> toSequence() {
		return prefix;
	}

	/*
	 * reinitialize tenv after serialization to another machine
	 */
	@SuppressWarnings("unchecked")
	private final PThreadEnvironment<ItemType> tenv() {
		if (tenv == null) {
			return (PThreadEnvironment<ItemType>) LocalEnvironment
					.env().getThreadEnv(threadIdx);
		}
		return tenv;
	}
}
